package cn.bellychang.PriorityLinkedList.wangwenjun;

import java.util.NoSuchElementException;
import java.util.Objects;

/**
 * @author: bellychang
 * @date: 2020/2/4
 */
public class PriorityLinkedList<E extends Comparable> {

    private static final String PLAIN_NULL = "null";
    private Node<E> head;

    private final Node<E> NULL = null;

    private PriorityLinkedList() {
        this.head = NULL;
    }

    private int size;

    public int size() {
        return this.size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public boolean contains(E element) {
        Node<E> temp = head;
        while (Objects.nonNull(temp)) {
            if (temp.value == element) {
                return true;
            }
            temp = temp.next;
        }
        return false;
    }

    public static <E extends Comparable> PriorityLinkedList<E> of(E... elements) {
        PriorityLinkedList list = new PriorityLinkedList();
        if (Objects.nonNull(elements)) {
            for (E element : elements) {
                list.addFirst(element);
            }
        }
        return list;
    }

    /**
     * By returning this can support chain programming
     * @param element
     * @return
     */
    public PriorityLinkedList<E> addFirst(E element) {
        Node<E> newNode = new Node<>(element);
        Node<E> previous = NULL;
        Node<E> current = head;
        // find the right place
        while (current != NULL && element.compareTo(current.getValue()) < 0) {
            previous = current;
            current = current.next;
        }
        // add head
        // two conditions: head == NULL || element.compareTo(head.getValue()) > 0  equals  previous == NULL
        if (previous == NULL) {
            head = newNode;
        } else {
            previous.next = newNode;
        }
        newNode.next = current;
        size++;
        return this;
    }


    @Override
    public String toString() {
        if (this.isEmpty()) {
            return PLAIN_NULL;
        }
        StringBuilder builder = new StringBuilder();
        Node<E> temp = head;
        while (Objects.nonNull(temp)) {
            builder.append(temp.toString()).append("->");
            temp = temp.next;
        }
        String result = builder.toString();
        return result.substring(0, result.length() - 2);
    }


    public E removeFirst() {
        if (this.isEmpty()) {
            throw new NoSuchElementException("this linked list is empty");
        }
        Node<E> temp = head;
        head = head.next;
        size--;
        return temp.getValue();
    }

    private static class Node<E> {
        private E value;

        private Node<E> next;

        public Node(E value) {
            this.value = value;
        }

        public E getValue() {
            return value;
        }

        @Override
        public String toString() {
            return value.toString();
        }
    }
}
